﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public enum TroopFightStateType
{
    None,
    AttackTroop,
    DefenseTroop,
}

public class Troop : MonoBehaviour
{
    public const int const_TroopRow = 5;
    public const int const_TroopColumn = 2;
    public const int const_UnitRowSpac = 2;
    public const int const_UnitColumnSpac = 2;

    //英雄播放攻击动作多久之后小兵冲出去
    public const float const_heroAtk_unitAtk = 1;

    private int _address;
    private int _troopIndex;
    private string _unitType;
    private bool _onlyOnePart;
    private int _totalUnitNum;
    private long _heroId;
    private int _protoId;
    private int _troopHp;
    private int[] _skills;
    private TroopFightStateType _troopFightState = TroopFightStateType.None;

    public TroopFightStateType TroopFightState
    {
        get { return _troopFightState; }
        set { _troopFightState = value; }
    }


    private Dictionary<int, List<int>> _doSkillTargetPartDic = new Dictionary<int, List<int>>();

    private Vector3 _troopCenterVec3;

    private List<Unit> _liveUnitList = new List<Unit>();

    //加一个英雄
    private TroopHero _hero;

    public List<Unit> LiveUnitList
    {
        get { return _liveUnitList; }
        set { _liveUnitList = value; }
    }

    public void Init(int troopIndex, string unitType, bool onlyOnePart, int totalUnitNum, long heroId, int protoId, int troopHp,string skills,int address)
    {
        _troopIndex = troopIndex;
        _unitType = unitType;
        _onlyOnePart = onlyOnePart;
        _totalUnitNum = totalUnitNum;
        //Debug.Log(_troopIndex);
        //Debug.Log(_totalUnitNum);
        _heroId = heroId;
        _protoId = protoId; 
        _troopHp = troopHp;
        _skills = new int[] { 0, 0, 0 };
        if (!string.IsNullOrEmpty(skills)) 
        {
            string[] s = skills.Split(':');
            for (int i = 0; i < s.Length; i++)
            {
                _skills[i] = int.Parse(s[i]);
            }
        }
        _address = address;
    }

    public void TroopHpChange(int changeValue, bool needAutoDead)
    {
        if (BattleMgr.Instance.ArmyInfoDic[_unitType]._useNodesNum >= 19)
        {
            if (changeValue < 0 && (_troopHp + changeValue) > 0)
            {
                for (int i = 0; i < _liveUnitList.Count; i++)
                {
                    _liveUnitList[0].InToHurtType();
                }
            }
        }
        if (changeValue < 0 && needAutoDead)
        {
            _getDamageNum = changeValue * -1;
            _needDeadNum = Mathf.Min(_liveUnitList.Count, Mathf.FloorToInt((float)changeValue * -1f / (float)_troopHp * _liveUnitList.Count));
            MakeUnitsDead(0.5f);
        }
        _troopHp += changeValue;

        if (_troopHp <= 0) 
        {
            PlayHeroDead();
            BattleMgr.Instance.PlayTroopDead(TroopIndex);
        }
    }

    public void BuildUnits()
    {
        Vector3 unitShape;
        int horizontalNum;
        int verticalNum;
        //if (_troopIndex >= 3)
        //{
        //    _troopCenterVec3 = new Vector3(0, 0, 6f * (_troopIndex - 2));
        //}
        //else
        //{
        //    _troopCenterVec3 = new Vector3(0, 0, 6f * (_troopIndex - 3));
        //}
        _troopCenterVec3 = BattleMgr.Instance.m_troopPos[_troopIndex];

        if (BattleMgr.Instance.ArmyInfoDic[_unitType]._useNodesNum == 5)
        {
            horizontalNum = 10;
            verticalNum = 6;
            unitShape = new Vector3(1.5f, 0, 1.5f);
        }
        else if (BattleMgr.Instance.ArmyInfoDic[_unitType]._useNodesNum == 13)
        {
            horizontalNum = 4;
            verticalNum = 2;
            unitShape = new Vector3(4f, 0f, 4f);
        }
        else
        {
            horizontalNum = 1;
            verticalNum = 1;
            unitShape = new Vector3(3.5f, 0f, 3.5f);
        }
        horizontalNum = Troop.const_TroopRow;
        verticalNum = Troop.const_TroopColumn;
        unitShape = new Vector3(Troop.const_UnitColumnSpac, 0, Troop.const_UnitRowSpac);


        int needRowNum = Mathf.CeilToInt((float)_totalUnitNum / (float)horizontalNum);
        if (_troopIndex >= 3)
        {
            float zOffset =  needRowNum * unitShape.z / 2f;
            for (int i = 0; i < needRowNum; i++)
            {
                if ((i == needRowNum-1) && (_totalUnitNum % horizontalNum != 0))
                {
                    int tempHorizontalNum = _totalUnitNum % horizontalNum;
                    Vector3 offsetPos = new Vector3(-1f * tempHorizontalNum * unitShape.x / 2f, 0,-1f * needRowNum * unitShape.z + zOffset);
                    for (int j = 0; j < tempHorizontalNum; j++)
                    {
                        Vector3 unitPos = offsetPos + _troopCenterVec3 + new Vector3((j + 0.5f) * unitShape.x, 0f, (i + 0.5f) * unitShape.z);
                        Vector3 localPos = unitPos + new Vector3(unitShape.x * Random.Range(-0.15f, 0.15f), 0f, unitShape.z * Random.Range(-0.15f, 0.15f));
                        CreateUnitGo(localPos);
                    }
                }
                else
                {
                    Vector3 offsetPos = new Vector3(-1f * horizontalNum * unitShape.x / 2f, 0, -1f * needRowNum * unitShape.z + zOffset);
                    for (int j = 0; j < horizontalNum; j++)
                    {
                        Vector3 unitPos = offsetPos + _troopCenterVec3 + new Vector3((j + 0.5f) * unitShape.x, 0f, (i + 0.5f) * unitShape.z);
                        Vector3 localPos = unitPos + new Vector3(unitShape.x * Random.Range(-0.15f, 0.15f), 0f, unitShape.z * Random.Range(-0.15f, 0.15f));
                        CreateUnitGo(localPos);
                    }
                }
            }
        }
        else
        {
            float zOffset = needRowNum * unitShape.z / 2f;
            for (int i = 0; i < needRowNum; i++)
            {
                if ((i == needRowNum-1) && (_totalUnitNum % horizontalNum != 0))
                {
                    int tempHorizontalNum = _totalUnitNum % horizontalNum;
                    Vector3 offsetPos = new Vector3(-1f * tempHorizontalNum * unitShape.x / 2f, 0, -1f * needRowNum * unitShape.z + zOffset);
                    for (int j = 0; j < tempHorizontalNum; j++)
                    {
                        Vector3 unitPos = offsetPos + _troopCenterVec3 + new Vector3((j + 0.5f) * unitShape.x, 0f, (needRowNum - i - 1 + 0.5f) * unitShape.z);
                        Vector3 localPos = unitPos + new Vector3(unitShape.x * Random.Range(-0.15f, 0.15f), 0f, unitShape.z * Random.Range(-0.15f, 0.15f));
                        CreateUnitGo(localPos);
                    }
                }
                else
                {
                    Vector3 offsetPos = new Vector3(-1f * horizontalNum * unitShape.x / 2f, 0, -1f * needRowNum * unitShape.z + zOffset);
                    for (int j = 0; j < horizontalNum; j++)
                    {
                        Vector3 unitPos = offsetPos + _troopCenterVec3 + new Vector3((j + 0.5f) * unitShape.x, 0f, (needRowNum - i - 1 + 0.5f) * unitShape.z);
                        Vector3 localPos = unitPos + new Vector3(unitShape.x * Random.Range(-0.15f, 0.15f), 0f, unitShape.z * Random.Range(-0.15f, 0.15f));
                        CreateUnitGo(localPos);
                    }
                }
            }
        }
    }

    public void BuildHero() 
    {
        int heroType = BattleMgr.GetHeroPath(_protoId);
        GameObject heroGo = Instantiate(BattleMgr.Instance.HeroPreDic[heroType]);
        _hero = heroGo.AddComponent<TroopHero>();
        //heroGo.transform.position = BattleMgr.Instance.m_troopPos[_troopIndex] + new Vector3(-10, 0, 0);

        heroGo.transform.position = BattleMgr.Instance.GetHeroPos(this);
        heroGo.transform.parent = this.transform;
        heroGo.transform.localScale = Vector3.one * 1.6f;
        heroGo.name = "hero"+_troopIndex.ToString();
        string sHeroType = BattleSettings.sHeroType[heroType];
        if(BattleSettings.s_bTestTroopNum){
            sHeroType = BattleSettings._batman;
        }
        _hero.Init(this,sHeroType);
    }

    private void GetUnitPosList()
    {

    }

    private void CreateUnitGo(Vector3 localPos)
    {
        GameObject unitGo = Instantiate(BattleMgr.Instance.UnitPrefabDic[_unitType]);
        unitGo.transform.parent = this.transform;
        unitGo.transform.localPosition = localPos;
        Unit u = unitGo.AddComponent<Unit>();
        u.Init(this);
        _liveUnitList.Add(u);
    }


    public Vector3 GetTroopCenter()
    {
        Vector3 troopCenter = Vector3.zero;
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            troopCenter += _liveUnitList[i].transform.position;
        }
        if (_liveUnitList.Count == 0)
        {
            if (_troopIndex < 3)
            {
                return new Vector3(0, 0, -30f + _troopIndex * 10f);
            }
            else
            {
                return new Vector3(0, 0, 10f + (_troopIndex - 3) * 10f);
            }
        }
        else
        {
            return troopCenter / _liveUnitList.Count;
        }
    }

    public Vector3 GetHeroHudPos()
    {
        return _hero.Pos();
    }

    void Update()
    {
        if (_startAttack)
        {
            if (BattleMgr.Instance.Timer >= _troopBackTime)
            {
                AttackFinish();
            }
        }
        if (_startBack)
        {
            if (BattleMgr.Instance.Timer >= _backFinishTime)
            {
                BackFinish();
            }
        }
        if (_startMeleeMultiAttack)
        {
            if (BattleMgr.Instance.Timer >= _meleeMultiAttackTime)
            {
                MeleeMultiAttackCheck();
            }
        }

        if (_startRush)
        {
            if (AllUnitSameState(UnitStateType.RushFinish)) 
            {
                RushFinish();
            }
        }
    }

    private bool _startRush = false;
    private float _rushTime = 0;
    private void RushFinish() 
    {
        _startRush = false;
        BattleMgr.Instance.TroopHpChange(_troopIndex, _fightTargetIndex, _makeDamageNum * -1, false, _isCri,true);
        BattleMgr.Instance.GetNowBattleFragment().OnAttackPartFinish();
    }

    public void RushAttackFinish(Unit attackUnit, List<Unit> unitBeAttackList, bool mustCheck = false)
    {
        for (int i = 0; i < unitBeAttackList.Count; i++)
        {
            unitBeAttackList[i].BeAttack(attackUnit);
            unitBeAttackList[i].InToHurtType();
        }
        if (!_meleeCheckDamage)
        {
            if (mustCheck || _attackPattern == BattleSettings._attackPat_Spec || _unitType == BattleSettings._titans)
            {
                _meleeCheckDamage = true;
                //BattleMgr.Instance.TroopDic[_fightTargetIndex].LiveUnitList[0].InToHurtType();
                BattleMgr.Instance.TroopDic[_fightTargetIndex].MakeUnitsDead(0.5f);
            }
            else
            {
                _meleeCheckDamage = true;

                //BattleMgr.Instance.TroopDic[_fightTargetIndex].LiveUnitList[0].InToHurtType();
                BattleMgr.Instance.TroopDic[_fightTargetIndex].CalculateMultiAttackDeadNum();
            }
        }
    }

    public bool AllUnitSameState(UnitStateType state) 
    {
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            if (_liveUnitList[i]._unitState != state)
            {
                return false;
            }
        }
        return true;
    }

    public void AttackFinish()
    {
        _startAttack = false;
        BattleMgr.Instance.TroopHpChange(_troopIndex, _fightTargetIndex, _makeDamageNum*-1,false,_isCri,true);
        BattleMgr.Instance.GetNowBattleFragment().OnAttackPartFinish();
    }

    public void BackFinish()
    {
        _startBack = false;
        BattleFragment bf = BattleMgr.Instance.GetNowBattleFragment();
        if (bf != null)
        {
            bf.OnAttackPartFinish();
        }
        // BattleMgr.Instance.GetNowBattleFragment().OnAttackPartFinish();
    }

    private bool _startBack = false;
    private float _backFinishTime = 0f;
    public void BackToOriginal(bool isAttack)
    {
        if (isAttack)
        {
            TroopBackToOriginalPos();
        }
        else 
        {
            TroopBackToFormation();
        }
        _troopFightState = TroopFightStateType.None;
        //_backFinishTime = BattleMgr.Instance.Timer + 1.3f;
        _backFinishTime = GetBackToFormationTime();
        _startBack = true;
    }

    private float GetBackToFormationTime()
    {
        float result = 0;
        for(int i = 0; i < _liveUnitList.Count; i++)
        {
            if(result < _liveUnitList[i].m_backToFormationTime)
            {
                result = _liveUnitList[i].m_backToFormationTime;
            }
        }
        //Debug.Log("回退的时间:   " + result);
        return result;
    }

    /// <summary>
    /// 进攻方归位
    /// </summary>
    public void TroopBackToOriginalPos()
    {
        _startAttack = false;
        List<Vector3> backVec3List = GetBackVecList();
        if (_troopIndex <= 2)
        {
            BattleCameraCtrl.Instance.ComeBack(_troopIndex);
        }
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            _liveUnitList[i].BackToOriginalPos(backVec3List[i]);
        }
    }

    public void TroopBackToFormation()
    {
        List<Vector3> backVec3List = GetBackVecList();
        List<Unit> needBackUnitList = new List<Unit>();
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            needBackUnitList.Add(_liveUnitList[i]);
        }

        for (int i = 0; i < backVec3List.Count; i++)
        {
            float minDis = 10000f;
            int targetUnitIndex = 0;
            for (int j = 0; j < needBackUnitList.Count; j++)
            {
                float dis = Vector3.Distance(backVec3List[i], needBackUnitList[j].transform.position);
                if (dis < minDis)
                {
                    targetUnitIndex = j;
                    minDis = dis;
                }
            }
            Unit backUnit = needBackUnitList[targetUnitIndex];
            needBackUnitList.RemoveAt(targetUnitIndex);
            backUnit.BackToFormation(backVec3List[i]);
        }
        /*
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            float minDis = 10000f;
            int targetPosIndex = 0;
            for (int j = 0; j < needBackVec3List.Count; j++)
            {
                float dis = Vector3.Distance(needBackVec3List[j], _liveUnitList[i].transform.position);
                if (dis < minDis)
                {
                    targetPosIndex = j;
                    minDis = dis;
                }
            }
            Vector3 targetVec3 = needBackVec3List[targetPosIndex];
            needBackVec3List.RemoveAt(targetPosIndex);
            _liveUnitList[i].BackToFormation(targetVec3);
        }
        */
    }

    private bool _meleeCheckDamage = false;

    public List<int> _meleeMultAttackNeedDeadNum;
    public int _nowCheckMeleeMultiAttackNum;



    public void CalculateMultiAttackDeadNum()
    {
        _meleeMultAttackNeedDeadNum = new List<int>();
        _nowCheckMeleeMultiAttackNum = 0;
        int needDeadNum = _needDeadNum / 3;
        int lastDeadNum = _needDeadNum - needDeadNum * 2;
        _meleeMultAttackNeedDeadNum.Add(needDeadNum);
        _meleeMultAttackNeedDeadNum.Add(needDeadNum);
        _meleeMultAttackNeedDeadNum.Add(lastDeadNum);
        // BattleMgr.Instance.TroopDic[_fightTargetIndex].MakeUnitsDead(1.5f);
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            _liveUnitList[i]._toZeroPointLength = Vector3.Distance(Vector3.zero, _liveUnitList[i].transform.position);
        }
        _liveUnitList.Sort(Unit.UnitSortFromZreo);
        MeleeMultiAttackCheck();
    }

    public bool _startMeleeMultiAttack;
    public float _meleeMultiAttackTime;

    private void MeleeMultiAttackCheck()
    {
        int needDeadNum = _meleeMultAttackNeedDeadNum[_nowCheckMeleeMultiAttackNum];
        float _attackPower = BattleMgr.Instance.ArmyInfoDic[BattleMgr.Instance.TroopDic[_fightTargetIndex].UnitType]._attackForce;
        List<Unit> needDeadUnitList = new List<Unit>();
        List<Unit> getDamageUnitList = new List<Unit>();
        List<Unit> notGetDamageUnitList = new List<Unit>();
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            if (_liveUnitList[i].BeAttackNum > 0)
            {
                getDamageUnitList.Add(_liveUnitList[i]);
            }
            else
            {
                notGetDamageUnitList.Add(_liveUnitList[i]);
            }
        }
        if (needDeadNum <= getDamageUnitList.Count)
        {
            while (needDeadNum > 0)
            {
                int needDeadIndex = Random.Range(0, getDamageUnitList.Count);
                needDeadUnitList.Add(getDamageUnitList[needDeadIndex]);
                getDamageUnitList.RemoveAt(needDeadIndex);
                needDeadNum -= 1;
            }
        }
        else
        {
            for (int i = 0; i < getDamageUnitList.Count; i++)
            {
                needDeadUnitList.Add(getDamageUnitList[i]);
            }
            needDeadNum -= getDamageUnitList.Count;
            while (needDeadNum > 0)
            {
                int needDeadIndex = 0;
                needDeadUnitList.Add(notGetDamageUnitList[needDeadIndex]);
                notGetDamageUnitList.RemoveAt(needDeadIndex);
                needDeadNum -= 1;
            }
        }
        for (int i = 0; i < needDeadUnitList.Count; i++)
        {
            _liveUnitList.Remove(needDeadUnitList[i]);
            needDeadUnitList[i].DoDead(_attackPower, 0.5f);
        }
        needDeadNum += 1;
        _nowCheckMeleeMultiAttackNum += 1;
        if (_nowCheckMeleeMultiAttackNum < 3)
        {
            _meleeMultiAttackTime = BattleMgr.Instance.Timer + 0.5f;
            _startMeleeMultiAttack = true;
        }
        else
        {
            _startMeleeMultiAttack = false;
        }
    }

    public void MeleeAttackFinish(Unit attackUnit, List<Unit> unitBeAttackList, bool mustCheck = false)
    {
        for (int i = 0; i < unitBeAttackList.Count; i++)
        {
            unitBeAttackList[i].BeAttack(attackUnit);
            unitBeAttackList[i].InToHurtType();
        }
        if (!_meleeCheckDamage)
        {
            if (mustCheck || _attackPattern == BattleSettings._attackPat_Spec || _unitType == BattleSettings._titans)
            {
                _meleeCheckDamage = true;
                //BattleMgr.Instance.TroopDic[_fightTargetIndex].LiveUnitList[0].InToHurtType();
                BattleMgr.Instance.TroopDic[_fightTargetIndex].MakeUnitsDead(0.5f);
            }
            else
            {
                _meleeCheckDamage = true;

                //BattleMgr.Instance.TroopDic[_fightTargetIndex].LiveUnitList[0].InToHurtType();
                BattleMgr.Instance.TroopDic[_fightTargetIndex].CalculateMultiAttackDeadNum();
            }
        }
    }

    public void UnitsDeadBySkill(int deadNum, float attackPower)
    {
        int needDeadNum = deadNum;
        Vector3 troopCenter = GetTroopCenter();
        List<Unit> needDeadUnitList = new List<Unit>();
        while (needDeadNum > 0)
        {
            int needDeadIndex = Random.Range(0, _liveUnitList.Count-1);
            needDeadUnitList.Add(_liveUnitList[needDeadIndex]);
            _liveUnitList.RemoveAt(needDeadIndex);
            needDeadNum -= 1;
        }

        for (int i = 0; i < needDeadUnitList.Count; i++)
        {
            needDeadUnitList[i].DoDead(troopCenter, attackPower);
        }
    }



    public void MakeUnitsDead(float lastTime)
    {
        float _attackPower = BattleMgr.Instance.ArmyInfoDic[BattleMgr.Instance.TroopDic[_fightTargetIndex].UnitType]._attackForce;
        List<Unit> needDeadUnitList = new List<Unit>();
        List<Unit> getDamageUnitList = new List<Unit>();
        List<Unit> notGetDamageUnitList = new List<Unit>();
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            if (_liveUnitList[i].BeAttackNum > 0)
            {
                getDamageUnitList.Add(_liveUnitList[i]);
            }
            else
            {
                notGetDamageUnitList.Add(_liveUnitList[i]);
            }
        }
        int needDeadNum = _needDeadNum;
        if (needDeadNum <= getDamageUnitList.Count)
        {
            while (needDeadNum > 0)
            {
                int needDeadIndex = Random.Range(0, getDamageUnitList.Count);
                needDeadUnitList.Add(getDamageUnitList[needDeadIndex]);
                getDamageUnitList.RemoveAt(needDeadIndex);
                needDeadNum -= 1;
            }
        }
        else
        {
            for (int i = 0; i < getDamageUnitList.Count; i++)
            {
                needDeadUnitList.Add(getDamageUnitList[i]);
            }
            needDeadNum -= getDamageUnitList.Count;
            while (needDeadNum > 0)
            {
                int needDeadIndex = Random.Range(0, notGetDamageUnitList.Count);
                needDeadUnitList.Add(notGetDamageUnitList[needDeadIndex]);
                notGetDamageUnitList.RemoveAt(needDeadIndex);
                needDeadNum -= 1;
            }
        }
        for (int i = 0; i < needDeadUnitList.Count; i++)
        {
            _liveUnitList.Remove(needDeadUnitList[i]);
            needDeadUnitList[i].DoDead(_attackPower, lastTime);
        }
    }

    public List<Vector3> GetBackVecList()
    {
        List<Vector3> backUnitsPosList = new List<Vector3>();
        int realLiveUnitNum = _liveUnitList.Count;
        int totalUnitsNum;
        Vector3 unitShape;
        int horizontalNum;
        int verticalNum;
        //if (_troopIndex >= 3)
        //{
        //    _troopCenterVec3 = new Vector3(0, 0, 10f * (_troopIndex - 2));
        //}
        //else
        //{
        //    _troopCenterVec3 = new Vector3(0, 0, 10f * (_troopIndex - 3));
        //}
        _troopCenterVec3 = BattleMgr.Instance.m_troopPos[_troopIndex];

        if (BattleMgr.Instance.ArmyInfoDic[_unitType]._useNodesNum == 5)
        {
            horizontalNum = 10;
            verticalNum = 6;
            unitShape = new Vector3(1.5f, 0, 1.5f);
        }
        else if (BattleMgr.Instance.ArmyInfoDic[_unitType]._useNodesNum == 13)
        {
            horizontalNum = 4;
            verticalNum = 2;
            unitShape = new Vector3(4f, 0f, 4f);
        }
        else
        {
            horizontalNum = 1;
            verticalNum = 1;
            unitShape = new Vector3(3.5f, 0f, 3.5f);
        }

        horizontalNum = Troop.const_TroopRow;
        verticalNum = Troop.const_TroopColumn;
        unitShape = new Vector3(Troop.const_UnitColumnSpac, 0, Troop.const_UnitRowSpac);


        totalUnitsNum = horizontalNum * verticalNum;
        int needRowNum = Mathf.CeilToInt((float)realLiveUnitNum / (float)horizontalNum);
        if (_troopIndex >= 3)
        {
            float zOffset = needRowNum * unitShape.z / 2f;
            for (int i = 0; i < needRowNum; i++)
            {
                if ((i == needRowNum - 1) && (realLiveUnitNum % horizontalNum != 0))
                {
                    int tempHorizontalNum = realLiveUnitNum % horizontalNum;
                    Vector3 offsetPos = new Vector3(-1f * tempHorizontalNum * unitShape.x / 2f, 0, -1f * needRowNum * unitShape.z + zOffset);
                    for (int j = 0; j < tempHorizontalNum; j++)
                    {
                        Vector3 unitPos = offsetPos + _troopCenterVec3 + new Vector3((j + 0.5f) * unitShape.x, 0f, (i + 0.5f) * unitShape.z) + new Vector3(unitShape.x * Random.Range(-0.15f, 0.15f), 0f, unitShape.z * Random.Range(-0.15f, 0.15f));
                        backUnitsPosList.Add(unitPos);
                    }
                }
                else
                {
                    Vector3 offsetPos = new Vector3(-1f * horizontalNum * unitShape.x / 2f, 0, -1f * needRowNum * unitShape.z + zOffset);
                    for (int j = 0; j < horizontalNum; j++)
                    {
                        Vector3 unitPos = offsetPos + _troopCenterVec3 + new Vector3((j + 0.5f) * unitShape.x, 0f, (i + 0.5f) * unitShape.z) + new Vector3(unitShape.x * Random.Range(-0.15f, 0.15f), 0f, unitShape.z * Random.Range(-0.15f, 0.15f));
                        backUnitsPosList.Add(unitPos);
                    }
                }
            }
        }
        else
        {
            float zOffset = needRowNum * unitShape.z / 2f;
            for (int i = 0; i < needRowNum; i++)
            {
                if (i == (needRowNum - 1) && (realLiveUnitNum % horizontalNum != 0))
                {
                    int tempHorizontalNum = realLiveUnitNum % horizontalNum;
                    Vector3 offsetPos = new Vector3(-1f * tempHorizontalNum * unitShape.x / 2f, 0, -1f * needRowNum * unitShape.z + zOffset);
                    for (int j = 0; j < tempHorizontalNum; j++)
                    {
                        Vector3 unitPos = offsetPos + _troopCenterVec3 + new Vector3((j + 0.5f) * unitShape.x, 0f, (needRowNum - i - 1 + 0.5f) * unitShape.z) + new Vector3(unitShape.x * Random.Range(-0.15f, 0.15f), 0f, unitShape.z * Random.Range(-0.15f, 0.15f));
                        backUnitsPosList.Add(unitPos);
                    }
                }
                else
                {
                    Vector3 offsetPos = new Vector3(-1f * horizontalNum * unitShape.x / 2f, 0, -1f * needRowNum * unitShape.z + zOffset);
                    for (int j = 0; j < horizontalNum; j++)
                    {
                        Vector3 unitPos = offsetPos + _troopCenterVec3 + new Vector3((j + 0.5f) * unitShape.x, 0f, (needRowNum - i - 1 + 0.5f) * unitShape.z) + new Vector3(unitShape.x * Random.Range(-0.15f, 0.15f), 0f, unitShape.z * Random.Range(-0.15f, 0.15f));
                        backUnitsPosList.Add(unitPos);
                    }
                }
            }
        }
        return backUnitsPosList;
    }

    public void Clear()
    {

    }
    
    #region 普攻方面
    private int _needDeadPeopleNum = 0;
    private float _deadNumPercentage;

    private bool _startAttack = false;
    private float _troopBackTime;
    private int _fightTargetIndex;
    private string _attackPattern;
    private bool _targetUnitCanFly;

    private int _makeDamageNum;
    private int _getDamageNum;
    private bool _isCri;

    public void GetSputteringAttack(int attackTroopIndex,int damageNum,bool isCri)
    {
        _getDamageNum = damageNum;
        _isCri = isCri;
        IntoDefenseState(attackTroopIndex, damageNum);
        MakeUnitsDead(0.5f);
        BattleMgr.Instance.TroopHpChange(attackTroopIndex, _troopIndex, damageNum * -1, false,isCri,true);
    }

    public void IntoAttackState(int fightTargetIndex, int damageNum,bool isCri)
    {
        //说要等英雄动作播一会之后小兵再攻击
        //英雄播放
        PlayHeroAttack();

        BattleMgr.Instance.AddInterval(delegate()
        {
            _startAttack = false;
            _makeDamageNum = damageNum;
            _fightTargetIndex = fightTargetIndex;
            _isCri = isCri;

            _targetUnitCanFly = BattleMgr.Instance.ArmyInfoDic[BattleMgr.Instance.TroopDic[fightTargetIndex].UnitType]._flyUnit == 1;
            _troopFightState = TroopFightStateType.AttackTroop;
            for (int i = 0; i < _liveUnitList.Count; i++)
            {
                _liveUnitList[i]._usePhy = true;
            }
            _troopHasTouch = false;
            Troop targetTroop = BattleMgr.Instance.TroopDic[_fightTargetIndex];
            _needDeadPeopleNum = Mathf.Min(targetTroop.LiveUnitList.Count, Mathf.FloorToInt((float)damageNum / (float)targetTroop.TroopHp * targetTroop.LiveUnitList.Count));
            _deadNumPercentage = (float)_needDeadPeopleNum / (float)targetTroop.LiveUnitList.Count;
            _meleeCheckDamage = false;
            BattleMgr.Instance.TroopDic[fightTargetIndex].IntoDefenseState(_troopIndex, damageNum);
            if (BattleMgr.Instance.ArmyInfoDic[_unitType]._attackPattern == BattleSettings._attackPat_Spec)
            {
                _attackPattern = BattleSettings._attackPat_Spec;
            }
            else
            {
                _attackPattern = BattleMgr.Instance.ArmyInfoDic[_unitType]._attackPattern;
                //去除对空中部队的 投射攻击
                /*
                if (_targetUnitCanFly)
                {
                    _attackPattern = BattleSettings._attackPat_Remote;
                }
                else
                {
                    //if (_unitType == BattleSettings._knight)
                    //{
                    //    _attackPattern = BattleSettings._attackPat_Rush;
                    //}
                    //else
                    //{
                    //    _attackPattern = BattleMgr.Instance.ArmyInfoDic[_unitType]._attackPattern;
                    //}

                    _attackPattern = BattleMgr.Instance.ArmyInfoDic[_unitType]._attackPattern;
                }*/
            }
            switch (_attackPattern)
            {
                case BattleSettings._attackPat_Melee:
                    TroopMarch(_deadNumPercentage);
                    break;
                case BattleSettings._attackPat_Remote:
                    TroopRemoteAttack();
                    break;
                case BattleSettings._attackPat_Spec:
                    TroopMarch(_deadNumPercentage);
                    break;
                case BattleSettings._attackPat_Rush:
                    TroopRush(_deadNumPercentage);
                    break;
            }
        }, const_heroAtk_unitAtk);
    }

    private int _totalRemoteUnitNum;
    private int _hasRemoteUnitNum;
    private bool _remoteCheckDamage = false;
    public int _oneShootNum = 3;

    public void TroopRemoteAttack()
    {
        DoRemoteAttack();
    }
    private void DoRemoteAttack() 
    {
        _hasRemoteUnitNum = 0;
        _totalRemoteUnitNum = _liveUnitList.Count * (_isCri ? 3 : 1) * _oneShootNum;
        int remoteUseActionIndex = 1;
        string targetTroopUnitType = BattleMgr.Instance.TroopDic[_fightTargetIndex].UnitType;
        ArmyInfo targetArmyInfo = BattleMgr.Instance.ArmyInfoDic[targetTroopUnitType];
        ArmyInfo mineArmyInfo = BattleMgr.Instance.ArmyInfoDic[UnitType];
        bool targetUnitCanFly = (targetArmyInfo._flyUnit == 1);
        if (mineArmyInfo._attackPattern == BattleSettings._attackPat_Melee)
        {
            remoteUseActionIndex = 2;
        }
        else if (mineArmyInfo._attackPattern == BattleSettings._attackPat_Remote)
        {
            if (targetUnitCanFly)
            {
                remoteUseActionIndex = 2;
            }
            else
            {
                remoteUseActionIndex = 1;
            }
        }
        _remoteCheckDamage = false;
        _troopFightState = TroopFightStateType.AttackTroop;
        _remoteStartCheck = false;
        BattleMgr.Instance.TroopDic[_fightTargetIndex].TroopFightState = TroopFightStateType.DefenseTroop;
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            _liveUnitList[i].DoRemote(remoteUseActionIndex, targetUnitCanFly,_isCri);
        }
    }


    private bool _remoteStartCheck = false;
    public void RemoteStart(float moveSpeed)
    {
        if (_remoteStartCheck == false)
        {
            _remoteStartCheck = true;
            if (_troopIndex <= 2)
            {
                BattleCameraCtrl.Instance.StartFollow(GetTroopCenter(), moveSpeed, _troopIndex <= 2);
            }
        }
    }

    public void RmoteAttackArrived()
    {
        if (!_remoteCheckDamage)
        {
            BattleMgr.Instance.TroopDic[_fightTargetIndex].LiveUnitList[0].InToHurtType();
            if (_troopIndex <= 2)
            {
                BattleCameraCtrl.Instance.StopFollow();
            }
            _remoteCheckDamage = true;
            List<Unit> unitList = new List<Unit>();
            BattleMgr.Instance.TroopDic[_fightTargetIndex].MakeUnitsDead(0.5f);
        }
        _hasRemoteUnitNum += 1;
        // BattleMgr.Instance.TroopDic[_fightTargetIndex].TroopBackToFormation();
        if (_hasRemoteUnitNum == _totalRemoteUnitNum)
        {
           // AttackFinish();
            _startAttack = true;
            _troopBackTime = BattleMgr.Instance.Timer + 0.25f;
        }
    }

    public Unit GetRandomUnit()
    {
        int partIndex = Random.Range(0, _liveUnitList.Count);
        return _liveUnitList[partIndex];
    }

    private int _needDeadNum;
    public void IntoDefenseState(int fightTargetIndex, int damageNum)
    {
        _fightTargetIndex = fightTargetIndex;
        _needDeadNum = Mathf.Min(_liveUnitList.Count, Mathf.FloorToInt((float)damageNum / (float)_troopHp * _liveUnitList.Count));
        _getDamageNum = damageNum;
        _troopFightState = TroopFightStateType.DefenseTroop;
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            _liveUnitList[i]._usePhy = true;
        }
    }

    public void TroopRush(float killPercent)
    {
        bool goForward;
        _startRush = true;
        Vector3 targetTroopCenterVec3 = BattleMgr.Instance.TroopDic[_fightTargetIndex].GetTroopCenter();
        Vector3 nowTroopCenterVec3 = GetTroopCenter();
        float length = Mathf.Abs(nowTroopCenterVec3.z - targetTroopCenterVec3.z);
        if (_fightTargetIndex >= 3)
        {
            goForward = true;
        }
        else
        {
            goForward = false;
        }
        float moveSpeed = BattleMgr.Instance.ArmyInfoDic[_unitType]._maxMoveSpeed;
        if (_troopIndex <= 2)
        {
            BattleCameraCtrl.Instance.StartFollow(GetTroopCenter(), moveSpeed, goForward);
        }
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            _liveUnitList[i].DoRushOne(length, goForward, killPercent);
        }
        float rushOneTime = (length - 9f) / moveSpeed;
        float touchTime = (9) / (moveSpeed * 1.5f);
        float rushTwoTime = (9 + 4.5f) / (moveSpeed * 1.5f);

    }

    public void TroopMarch(float killPercent)
    {
        bool goForward;
        Vector3 targetTroopCenterVec3 = BattleMgr.Instance.TroopDic[_fightTargetIndex].GetTroopCenter();
        if (_fightTargetIndex >= 3)
        {
            goForward = true;
        }
        else
        {
            goForward = false;
        }
        float moveSpeed = BattleMgr.Instance.ArmyInfoDic[_unitType]._maxMoveSpeed;
        if (_troopIndex <= 2)
        {
            BattleCameraCtrl.Instance.StartFollow(GetTroopCenter(), moveSpeed, goForward);
        }
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            _liveUnitList[i].DoMarch(targetTroopCenterVec3.z, goForward, killPercent);
        }
    }

    private bool _troopHasTouch = false;
    public void TroopTouch()
    {
        if (_troopHasTouch == false)
        {
            _troopHasTouch = true;
            if (_troopIndex <= 2)
            {
                BattleCameraCtrl.Instance.StopFollow();
            }
            for (int i = 0; i < _liveUnitList.Count; i++)
            {
                _liveUnitList[i].FixedMarchSpeed();
            }
        }
    }

    public void TroopPlaySkillAction()
    {
        _skillActionHasCheck = false;
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            _liveUnitList[i].DoSkillAction();
        }
    }

    public void PlayHeroSkillAction() 
    {
        if (BattleSettings.s_bShowHero)
        {
            _hero.DoSkill();
        }
    }

    public void TroopPlaySingSkillAction()
    {
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            _liveUnitList[i].DoSingSkillAction();
        }
    }

    public void PlayHeroSingSkillAction()
    {
        if (BattleSettings.s_bShowHero)
        {
            _hero.DoSkill();
            DKLuaUtil.AddEffById("20028", _hero.gameObject, Vector3.zero, false, 0, 1, true, 5, null, null, null);
        }
    }


    public void PlayHeroAttackBySkill() 
    {
        if (BattleSettings.s_bShowHero)
        {
            _hero.AttckBySkill();
        }
    }
    public void PlayHeroDead() 
    {
        if (BattleSettings.s_bShowHero)
        {
            _hero.DoDead();
        }
    }

    public void PlayHeroAttack() 
    {
        if (BattleSettings.s_bShowHero)
        {
            _hero.DoAttack();
        }
    }


    private bool _skillActionHasCheck = false;
    public void OnSkillActionCheck()
    {
        if (!_skillActionHasCheck)
        {
            _skillActionHasCheck = true;
            Debug.Log("Real Check!!!!!!");
            BattleMgr.Instance.GetNowBattleFragment().RealPlayEffect();
        }
    }

    public void OnSingActionCheck() 
    {
        BattleMgr.Instance.GetNowBattleFragment().ContineFragmentState();
    }

    public void StartMeleeAttack()
    {
        if (_startAttack == false)
        {
            _startAttack = true;
            _troopBackTime = BattleMgr.Instance.Timer + 3f;
        }
    }

    public List<Unit> GetBeAttackUnitList(Unit attackUnit, Unit beAttackUnit, int attackIndex)
    {
        List<Unit> unitList = new List<Unit>();
        ActionInfo ai = BattleMgr.Instance.BattleActionInfoDic[attackUnit.Troop.UnitType][attackIndex];
        if (ai._unitAttackSingle == 1)
        {
            unitList.Add(beAttackUnit);
        }
        else
        {
            float attackAngle = BattleMgr.GetAngle(beAttackUnit.transform.position - attackUnit.transform.position);
            unitList = GetAoeAttackUnitList(attackUnit.transform.position, ai._aoeAngle, attackAngle, ai._aoeRange);
        }
        return unitList;
    }

    public List<Unit> GetAoeAttackUnitList(Vector3 centerPos, float angle, float lookAtAngle, float length)
    {
        List<Unit> returnUnitList = new List<Unit>();
        float lookAngle = lookAtAngle;
        if (lookAtAngle < 180)
        {
            lookAngle += 360;
        }
        for (int i = 0; i < _liveUnitList.Count; i++)
        {
            if (Vector3.Distance(_liveUnitList[i].transform.position, centerPos) <= length)
            {
                if (_liveUnitList[i].transform.position == centerPos)
                {
                    returnUnitList.Add(_liveUnitList[i]);
                }
                else
                {
                    float unitDir = BattleMgr.GetAngle(_liveUnitList[i].transform.position - centerPos);
                    if (unitDir < 180)
                    {
                        unitDir += 360;
                    }
                    if ((unitDir >= lookAngle - angle / 2f) && (unitDir <= lookAngle + angle / 2f))
                    {
                        returnUnitList.Add(_liveUnitList[i]);
                    }
                }
            }
        }
        return returnUnitList;
    }

    #endregion


    #region 属性
    public int TroopIndex
    {
        get { return _troopIndex; }
        set { _troopIndex = value; }
    }
    public string UnitType
    {
        get { return _unitType; }
        set { _unitType = value; }
    }
    public long HeroId
    {
        get { return _heroId; }
    }
    public int ProtoId
    {
        get { return _protoId; }
    }
    public int TroopHp
    {
        get { return _troopHp; }
        set { _troopHp = value; }
    }

    public Dictionary<int, List<int>> DoSkillTargetPartDic
    {
        get
        {
            return _doSkillTargetPartDic;
        }

        set
        {
            _doSkillTargetPartDic = value;
        }
    }

    public int FightTargetIndex
    {
        get { return _fightTargetIndex; }
        set { _fightTargetIndex = value; }
    }

    public string AttackPattern
    {
        get { return _attackPattern; }
        set { _attackPattern = value; }
    }

    public bool TargetUnitCanFly
    {
        get { return _targetUnitCanFly; }
        set { _targetUnitCanFly = value; }
    }

    public bool IsLeft 
    {
        get
        {
            if (TroopIndex < 3)
            {
                return true;
            }
            else 
            {
                return false;
            }
        }
    }

    public int[] Skills 
    {
        get { return _skills; }
    }

    public int Address
    {
        get { return _address; }
    }

    #endregion
}